﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="BBU.cs" company="">
//   
// </copyright>
// <summary>
//   The bbu.
// </summary>
// --------------------------------------------------------------------------------------------------------------------


using System;
using System.Collections.Generic;
using System.Linq;
using Systemathics.FrameWork;

namespace Systemathics.Indicators
{

    [Serializable]
    public sealed class Volatility : Indicator
    {
        private readonly Decimal a;
        private readonly Decimal b;
        private readonly Decimal c;
        private readonly Queue<Decimal> queue;
        private Decimal muYield, Value_t_1, Yield;
        private Decimal sigma_squarre;

        public int Length { get; private set; }

        public Volatility(Instrument instr, Data dt, BarType bt, int value, int length) : base(instr, dt, bt, value)
        {
            Length = length;

            a = (Decimal)(Length - 1) / Length;
            b = 1 / (Decimal)Length;
            c = 1 / (Decimal)(Length - 1);
            muYield = 0;
            sigma_squarre = 0;
            queue = new Queue<Decimal>();
        }


        protected override void Calculate(object price)
        {
            if (price is Bar)
            {
                var bar = price as Bar;
                Calculate(bar.BeginTime, bar.Median);
            }
            else if (price is Quote)
            {
                var quote = price as Quote;
                Calculate(quote.Time, quote.Mid);
            }
            else
            {
                var trade = price as Trade;
                Calculate(trade.Time, trade.Price);
            }
        }

        private void Calculate(DateTime time, Decimal value)
        {
            if (queue.Count < Length)
            {
                if (Value_t_1 != 0)
                {
                    Yield = value/Value_t_1 - 1;
                    queue.Enqueue(Yield);
                    muYield = queue.Average();
                }
            }
            else
            {
                Yield = (value/Value_t_1 - 1);
                muYield = a * muYield + b * Yield;
                sigma_squarre = (a * sigma_squarre + c * (Yield - muYield) * (Yield - muYield));
                Add(time, (decimal) Math.Sqrt((double) sigma_squarre));
                IndicatorCalculated(this);
            }
            Value_t_1 = value;
        }
    }
}